home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Ken Long / CircularWDEF / circularWDEF.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-04  |  13.6 KB  |  384 lines  |  [TEXT/KAHL]

  1. /*
  2. From ndsuvm1!cunyvm!psuvm.bitnet!ukma!husc6!think!ephraim Tue Feb 23 08:56:14 CST 1988
  3. Article 32 of comp.sys.mac.programmer:
  4. Path: ndsuvax!ndsuvm1!cunyvm!psuvm.bitnet!ukma!husc6!think!ephraim
  5. >From: ephraim@think.COM (ephraim vishniac)
  6. Newsgroups: comp.sys.mac.programmer
  7. Subject: A Custom WDEF
  8. Message-ID: <16995@think.UUCP>
  9. Date: 22 Feb 88 15:59:09 GMT
  10. Sender: usenet@think.UUCP
  11. Reply-To: ephraim@think.UUCP (ephraim vishniac)
  12. Organization: Thinking Machines Corporation, Cambridge, MA
  13. Lines: 345
  14.  
  15. Since mentioning in a comp.sys.mac article that I had seen a circular
  16. window on the Mac, several people have asked for source code or a copy
  17. of the program.  Following is the help text from the program called
  18. "Windows Demo."  The program features a variety of unusual window
  19. types, and the help text explains how they are produced.
  20. I will send the actual program (and this text) to info-mac, so that
  21. internet users can retrieve it from sumex.  Even though it was
  22. compiled long ago with Megamax C, the program now runs on a Mac II - I
  23. just patched all those nasty 02B6's to 0A78's and there's no problem
  24. any more.
  25. ----------------------  Start of Help Text  -------------------------
  26. Program by Richard Koch
  27.            Department of Mathematics
  28.            University of Oregon
  29.            Eugene, Oregon 97403
  30.    The Macintosh toolbox contains routines which move windows, resize
  31. them, and so forth. These routines are quite complicated; when a
  32. window is moved, the system must erase the old version of the window,
  33. draw the window in its new position, draw newly exposed portions of
  34. other windows, and recalculate the visible portions of all windows. It
  35. is natural to suppose that the toolbox routines which do these things
  36. assume that windows are rectangular, but in fact the routines have
  37. been written to handle windows of any shape whatever.
  38.    Most Macintosh programmers use one of the six predefined windows at
  39. the left; these windows are basically rectangular (the final window
  40. has curved corners). But it is easy to define other window shapes.
  41. Windows can have holes in the middle, curved borders, fancy frames,
  42. and other unusual features.
  43.    Some Macintosh users believe that the computer keeps a complete
  44. copy of each window in memory even when the window is not visible on
  45. the screen. But that is not correct. The Macintosh knows how to draw
  46. window frames and redraws portions of these frames when they become
  47. visible. But the contents of windows are the responsibility of
  48. programs; the Macintosh issues a warning when a previously hidden
  49. portion of a window becomes visible, and the program does whatever it
  50. wishes. The program you are running is lazy and erases windows
  51. entirely when new portions become visible; by turning this feature
  52. off, you can see that the toolbox erases each newly visible portion of
  53. a window before reporting that it should be redrawn.
  54.    Since round windows require extensive calculations, they slow the
  55. system down enough to let us see the window moving algorithms in
  56. operation. If a window is moved from one portion of the screen to
  57. another, the toolbox directly moves screen memory and no redrawing is
  58. necessary. It is easier for the toolbox to make this pixel move when
  59. the window moves up than when the window moves down. If a window is
  60. moved part way off the screen and later moved back on, the toolbox
  61. copies those portions still on the screen by a direct memory move, but
  62. remaining portions of the window frame and contents must be redrawn.
  63.    To produce an unusual window, it is only necessary to write one
  64. function of the form
  65.    long MyWindow(varCode, theWindow, message, param)
  66.    int varCode, message; WindowPtr theWindow; long param;
  67. This function is called by the toolbox when the toolbox needs to know
  68. the shape of the entire window or its content region, when it needs to
  69. know where the mouse went down in the window, or when it needs to draw
  70. the window frame. All other Macintosh window operations are handled
  71. automatically without help from the programmer. The parameter
  72. "message" explains what operation to perform, and the parameter
  73. "param" contains additional information for some requests. It is
  74. possible to create several related windows with only minor variations
  75. in appearance; the parameter varCode explains which variant to use.
  76. This parameter must be between 0 and 15.
  77.    The code for "MyWindow" can be put in the main program code area,
  78. or it can be placed in a resource of type WDEF. In the program you are
  79. running, code for the rectangular and square windows is included with
  80. other program code, but code for the round windows is in a WDEF
  81. resource with ID #128.
  82.    The Macintosh system contains two WDEF resources with ID's 0 and 1 which define all of the standard windows on the left. The firs
  83.    When the Macintosh is running a program and needs a resource, it
  84. first searches the program file for the resource and only searches the
  85. system file if the resource cannot be found in the program file.
  86. Consequently, it is possible to trick programs so they will produce
  87. round windows rather than rectangular windows. Using ReEdit, cut the
  88. entire WDEF resource from the program you are running and paste it
  89. into MacWrite. Then change its resource ID # from 128 to 0. When you
  90. run the resulting MacWrite, it will use round windows for all
  91. operations. (Warning: Text written into MacWrite will disappear under
  92. the frame of the round window, and the "OK" box for some dialogs will
  93. be hidden beyond the window frame. Often a dialog will accept "RETURN"
  94. as the equivalent of clicking on "OK," but otherwise you will be stuck
  95. and have to reset the computer.)
  96.    The round window WDEF can be pasted into the FINDER itself,
  97. yielding a round directory.
  98.    It is easy to use the round window from this program in your own
  99. programs. Simply copy WDEF #128 into your resources and change its ID
  100. number as appropriate. Your resource code should also contain a window
  101. definition somewhat like
  102.    TYPE WIND
  103.     ,128                ;  window resource ID
  104.    First Round Window   ;  window title
  105.    40 80 120 300        ;  top left bottom right
  106.    Visible NoGoAway     ;  window status
  107.    2048                 ;  WindProcID (see below)
  108.    0                    ;  RefCon
  109.    The actual program code will create this window in the usual way
  110. using a line like
  111.    wp = GetNewWindow(128, wStorage, -1L);
  112.    Of course this last line will be different if you are using another
  113. language, but everything else will be the same.
  114.    The only strange feature here is the rule for assigning the
  115. WindProcID number. This number should equal sixteen times the WDEF
  116. resource number of the appropriate window definition code plus the
  117. varCode of the window variant. For example, the first five windows
  118. pictured at the left are produced by WDEF #0 in the system file with
  119. varCodes 0 through 5, so their WindProcID's are 0 through 5. The sixth
  120. window to the left is produced by WDEF #1 in the system file using
  121. varCode 0, so its WindProcID is 16.
  122.    The WDEF for round windows allows sixteen possible variants. The
  123. rightmost bit in the variant number is 1 if the window has a title and
  124. 0 otherwise. The next bit left is 1 if the window has no grow box and
  125. 0 otherwise. The next bit is 1 if the window has a fancy woven frame
  126. and 0 otherwise. The final left bit is 1 if the title appears on the
  127. top and 0 if it appears on the bottom. So the variant number for a
  128. window with a title, grow box, fancy frame, and title at the top is: 
  129. 1 + 2 * 0 + 4 * 1 + 8 * 1 = 13.
  130.    If you want to change the appearance of the round windows from this
  131. program, you will have to rewrite the code for "MyWindow." Below is
  132. this code, written using Megamax C.*/
  133. //#include <qd.h>
  134. //#include <qdvars.h>
  135. //#include <win.h>
  136. //#include <menu.h>
  137. //#include <event.h>
  138. //#include <dialog.h>
  139.  
  140. /* Optional:
  141. pascal long myWindowWDEF(int varCode, WindowPeek theWindow, int message, long param)
  142. */
  143.  
  144. pascal long main(int varCode, WindowPeek theWindow, int message, long param)
  145.     typedef Rect *RPtr;
  146.     Rect r, rclose[4], rgrow, rtitle;
  147.     int i,j,k;
  148.     Point p;
  149.     GrafPtr temp;
  150.     PenState pnState;
  151.     RgnHandle hstructure, hcontent, frame, htitle;
  152.     Pattern pat;
  153.     Str255 title;
  154.     GetPort(&temp); SetPort((GrafPtr)theWindow);
  155.     r = (*((GrafPtr)theWindow)).portRect;
  156.     i = r.right - r.left; j = r.bottom - r.top;
  157.     if (i > j) 
  158.         i = j;
  159.     r.left = 0; r.top = 0;
  160.     LocalToGlobal(&(r));
  161.     SetPort(temp);
  162.     r.bottom = r.top + i; r.right = r.left + i;
  163.     
  164.     SetRect(&rclose[0],r.left + 3,r.top + i/2 - 6,
  165.                     r.left + 14,r.top + i/2 + 5);
  166.                     
  167.     SetRect(&rclose[1],r.right - 14,r.top + i/2 -6,
  168.                     r.right -3,r.top + i/2 + 5);
  169.                     
  170.     SetRect(&rclose[2],r.left + i/2 - 6,r.top + 3,
  171.                     r.left + i/2 + 5,r.top + 14);
  172.                     
  173.     SetRect(&rclose[3],r.left + i/2 - 6,r.bottom -14,
  174.                     r.left + i/2 + 5,r.bottom -3);
  175.                     
  176.     rgrow.right = r.left + i/2 + ((i/2)*10)/14;
  177.     rgrow.bottom =  r.top  + i/2 + ((i/2)*10)/14;
  178.     rgrow.left = rgrow.right - (9*141)/100;
  179.     rgrow.top = rgrow.bottom - (9*141)/100;
  180.     for (k = 0; k < 256; k++) title[k] =
  181.     *(*((*theWindow).titleHandle) + k);
  182. //        ptocstr(&title);
  183.     j = StringWidth(&title) / 2 + 15;
  184.     rtitle.left = r.left + i/2 - j;
  185.     rtitle.right = rtitle.left + j + j;
  186.     if (varCode & 0x0008) 
  187.     {
  188.         rtitle.top = r.top;
  189.         rtitle.bottom = r.top + 16;
  190.     }
  191.     else
  192.         {
  193.             rtitle.bottom = r.bottom;
  194.             rtitle.top = r.bottom - 16;
  195.     }
  196.     p.v = HiWord(param); p.h = LoWord(param);
  197.     hstructure = (*theWindow).strucRgn;
  198.     hcontent = (*theWindow).contRgn;
  199.     switch(message)
  200.     {
  201.         case 0: 
  202.             if ((*theWindow).visible) 
  203.             {
  204.                 if (param == 0L)  
  205.                 {
  206.                     GetPenState(&pnState);
  207.                     PenSize(18,18);PenMode(patBic);
  208.                     FrameOval(&r);
  209.                     SetPenState(&pnState);
  210.                     if (((*theWindow).hilited) && (varCode &0x0004)) 
  211.                     {
  212.                         pat[0] = 0xF8; pat[1] = 0x74;
  213.                         pat[2] = 0x22; pat[3] = 0x47;
  214.                         pat[4] = 0x8F; pat[5] = 0x17;
  215.                         pat[6] = 0x22; pat[7] = 0x71;
  216.                         FrameOval(&r);InsetRect(&r,1,1);
  217.                         FrameOval(&r);InsetRect(&r,1,1);
  218.                         frame = NewRgn();OpenRgn();
  219.                         FrameOval(&r);InsetRect(&r,13,13);
  220.                         FrameOval(&r);CloseRgn(frame);
  221.                         FillRgn(frame,&pat);DisposeRgn(frame);
  222.                         FrameOval(&r);InsetRect(&r,1,1);
  223.                         FrameOval(&r);
  224.                     }    //• if hitlited and varcode at 0004
  225.                     else 
  226.                         {
  227.                             FrameOval(&r);InsetRect(&r,3,3);
  228.                             if ((*theWindow).hilited)
  229.                                 for (i = 0; i < 6; i++) 
  230.                                 {
  231.                                     FrameOval(&r);InsetRect(&r,2,2);
  232.                                 }
  233.                             else 
  234.                                 InsetRect(&r,12,12);
  235.                                 InsetRect(&r,1,1);FrameOval(&r);
  236.                     }
  237.                     if (((*theWindow).hilited) && ((*theWindow).goAwayFlag)) 
  238.                     {
  239.                         for (i = 0; i < 4; i++) 
  240.                         {
  241.                             EraseRect(&rclose[i]);
  242.                             FrameRect(&rclose[i]);}
  243.                         }
  244.                         if (((*theWindow).hilited) && ((varCode & 0x0002) == 0))
  245.                         {
  246.                             EraseRect(&rgrow); FrameRect(&rgrow);}
  247.                             if (varCode & 0x0001) 
  248.                             {
  249.                                 EraseRect(&rtitle);FrameRect(&rtitle);
  250.                                 if ((*theWindow).hilited) 
  251.                                 {
  252.                                     InsetRect(&rtitle,1,1);
  253.                                     FrameRect(&rtitle);
  254.                                     InsetRect(&rtitle,-1,-1);
  255.                                     MoveTo(rtitle.left + 15,
  256.                                     rtitle.top + 13);
  257.                                     DrawString(&title);
  258.                                 }
  259.                             }
  260.                         }    //• if hilited and varcode at 0002
  261.                         else 
  262.                             if (param == 4L) 
  263.                             {
  264.                                 GetPenState(&pnState);
  265.                                 PenMode(patXor);
  266.                                 for (i = 0; i < 4; i++)
  267.                                     if ((i == 2) && (varCode & 1) && (varCode & 8))
  268.                                         ;    //• do nada!
  269.                                     else 
  270.                                         if ((i == 3) && (varCode & 1) && !(varCode & 8))
  271.                                             ;    //• do nada!
  272.                                         else 
  273.                                             {
  274.                                                 MoveTo(rclose[i].left+2,
  275.                                                         rclose[i].top+2);
  276.                                                 Line(6,6);
  277.                                                 MoveTo(rclose[i].left+2,
  278.                                                             rclose[i].bottom-3);
  279.                                                 Line(6,-6);
  280.                                                 MoveTo(rclose[i].left+1,
  281.                                                             rclose[i].top + 5);
  282.                                                 Line(8,0);
  283.                                                 MoveTo(rclose[i].left+5,
  284.                                                             rclose[i].top+1);
  285.                                                 Line(0,8);
  286.                                                 InsetRect(&rclose[i],4,4);
  287.                                                 EraseRect(&rclose[i]);
  288.                                         }
  289.                                         SetPenState(&pnState);
  290.                             }    //• if param 4L.
  291.                     }    //if hilited and goAwayFlag.    
  292.                 }    //• if param 0L.
  293.             }    //• if visible.
  294.             return(0L); 
  295.         break;
  296.             
  297.         case 1: 
  298.             if (PtInRgn(p,hcontent)) 
  299.                 return(1L);
  300.             else 
  301.                 if ((PtInRect(p,&rclose[0])) &&
  302.                         ((*theWindow).goAwayFlag)  &&
  303.                         ((*theWindow).hilited))
  304.                     return(4L);
  305.                 else 
  306.                     if ((PtInRect(p,&rclose[1])) &&
  307.                         ((*theWindow).goAwayFlag)  &&
  308.                         ((*theWindow).hilited))
  309.                         return(4L);
  310.                 else 
  311.                     if ((PtInRect(p,&rclose[2])) &&
  312.                         ((*theWindow).goAwayFlag)  &&
  313.                         ((*theWindow).hilited)    &&
  314.                         (!((varCode & 1)        &&
  315.                         (varCode & 8))))
  316.                         return(4L);
  317.                 else 
  318.                     if ((PtInRect(p,&rclose[3])) &&
  319.                         ((*theWindow).goAwayFlag)  &&
  320.                         (!((varCode & 1)        &&
  321.                         !(varCode & 8)))        &&
  322.                         ((*theWindow).hilited))
  323.                         return(4L);
  324.                 else 
  325.                     if ((PtInRect(p,&rgrow))    &&
  326.                         ((varCode & 0x0002) == 0)  &&
  327.                         ((*theWindow).hilited))
  328.                         return(3L);
  329.                 else 
  330.                     if (PtInRgn(p, hstructure))
  331.                         return(2L);
  332.                 else 
  333.                     return(0L); 
  334.         break;
  335.         
  336.         case 2: 
  337.             SetEmptyRgn(hstructure);
  338.             OpenRgn();
  339.             FrameOval(&r);
  340.             CloseRgn(hstructure);
  341.             if (varCode & 0x0001) 
  342.             {
  343.                 htitle = NewRgn();
  344.                 RectRgn(htitle, &rtitle);
  345.                 UnionRgn(hstructure, htitle, hstructure);
  346.                 DisposeRgn(htitle);
  347.             }
  348.             InsetRect(&r,18,18);
  349.             SetEmptyRgn(hcontent);
  350.             OpenRgn();
  351.             FrameOval(&r);
  352.             CloseRgn(hcontent);
  353.         break;
  354.         
  355.         case 3: 
  356.             return(0L); 
  357.         break;
  358.         
  359.         case 4: 
  360.             return(0L); 
  361.         break;
  362.         
  363.         case 5: 
  364.             r = *(RPtr)param;
  365.             i = r.right - r.left;
  366.             j = r.bottom - r.top;
  367.             if (i > j) i = j;
  368.             r.right = r.left + i;
  369.             r.bottom = r.top + i;
  370.             FrameOval(&r); return(0L); 
  371.         break;
  372.         
  373.         case 6: 
  374.             return(0L); 
  375.         break;
  376.     }    //• switch
  377. }            /*
  378. ----------------------  End of Help Text  ---------------------------------
  379. Ephraim Vishniac                                        ephraim@think.com
  380. Thinking Machines Corporation / 245 First Street / Cambridge, MA 02142-1214
  381. */
  382.  
  383.